package org.happycomp.radiog;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.window.ToolTip;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.happycomp.radio.ProcessStates;
import org.happycomp.radio.StopDownloadCondition;
import org.happycomp.radio.downloader.DownloadingItem;
import org.happycomp.radio.downloader.impl.IvalidPlaylistContentException;
import org.happycomp.radio.planner.PlannedItem;
import org.happycomp.radio.scheduler.SchedulerListener;
import org.happycomp.radiog.core.StopTimeCondition;

public class ContentView extends ViewPart implements SchedulerListener, ISelectionListener  {
	
	public static final Logger LOGGER = Logger.getLogger(ContentView.class.getName());
	public static final SimpleDateFormat TABLE_DATE_FORMATTER = new SimpleDateFormat("HH:mm   dd.MM.yyyy");

	public TableViewer downloading;
	public TableViewer planned;
	
	private CLabel justPoppedLabel;
	
	private SelectionProviderIntermediate selectionProviderIntermediate;
	private FontRegistry fontRegistry;
	private CLabel shutdownDate;
	
	public ContentView() {
		
	}

	
	@Override
	public void createPartControl(Composite parent) {
		SashForm sashForm = new SashForm(parent, SWT.VERTICAL );
		plannedTable(sashForm);
		downloadingTable(sashForm);

		sashForm.setWeights(new int[] {40,60});
		
		Activator.getDefault().getRadioScheduler().addSchedulerListener(this);
		this.selectionProviderIntermediate = new SelectionProviderIntermediate();
		
		getSite().getPage().addSelectionListener(this);
		getSite().setSelectionProvider(this.selectionProviderIntermediate);
	}

	private void plannedTable(SashForm sashForm) {
		Composite composite = new Composite(sashForm, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);

		GridData gdata = new GridData();

		CLabel clabel = new CLabel(composite, SWT.NONE);
		clabel.setLayoutData(gdata);
		clabel.setText("Naplanovane ulohy:");
		
		gdata = new GridData();
		gdata.horizontalSpan = 2;
		gdata.horizontalAlignment = SWT.FILL;
		gdata.verticalAlignment = SWT.FILL;
		gdata.grabExcessHorizontalSpace = true;
		gdata.grabExcessVerticalSpace =true;
		gdata.minimumHeight = 100;
		gdata.minimumWidth = 100;
		
		
		planned = new TableViewer(composite, SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		planned.addSelectionChangedListener(new ISelectionChangedListener() {
			
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				selectionProviderIntermediate.setSelectionProviderDelegate(event.getSelectionProvider());
				selectionProviderIntermediate.fireSelectionChanged(event.getSelection());
			}
		});
		PlannedTableColumns.configureTable(planned);
		planned.setContentProvider(new TableContentProvider());
		planned.setLabelProvider(new TableLabelProvider());
		planned.setInput(Activator.getDefault().getRadioScheduler().getPlanner().getPlannedItems());
		planned.getTable().setLayoutData(gdata);
	}

	private void downloadingTable(SashForm sashForm) {
		Composite composite = new Composite(sashForm, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		composite.setLayout(layout);

		GridData  gdata = new GridData();
		gdata.horizontalSpan = 2;
		gdata.horizontalAlignment = SWT.FILL;
		gdata.grabExcessHorizontalSpace = true;
		
		Composite infosPane = createInformationPane(composite);
		infosPane.setLayoutData(gdata);
		
		
//		CLabel preparingLabel = new CLabel(composite, SWT.NONE);
//		preparingLabel.setLayoutData(gdata);
//		preparingLabel.setText("Pripravuje se:");
//
//		gdata = new GridData();
//		gdata.horizontalSpan = 1;
//		gdata.horizontalAlignment = SWT.FILL;
//		gdata.grabExcessHorizontalSpace = true;
//
//		justPoppedLabel = new CLabel(composite, SWT.NONE);
//		justPoppedLabel.setLayoutData(gdata);
//
//
//		gdata = new GridData();
//		gdata.horizontalSpan = 1;
//		gdata.horizontalAlignment = SWT.FILL;
//		gdata.grabExcessHorizontalSpace = true;
//
//		CLabel shutdownLabel = new CLabel(composite, SWT.NONE);
//		shutdownLabel.setText("Vypnuti:");
//		shutdownLabel.setLayoutData(gdata);

		gdata = new GridData();
		gdata.horizontalSpan = 2;
		gdata.grabExcessHorizontalSpace=true;
		gdata.horizontalAlignment = SWT.FILL;
		Label separatorLabel = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
		separatorLabel.setLayoutData(gdata);

		gdata = new GridData();
		CLabel downloadingLabel = new CLabel(composite, SWT.NONE);
		downloadingLabel.setLayoutData(gdata);
		downloadingLabel.setText("Stahovani:");

		gdata = new GridData();
		gdata.horizontalSpan = 2;
		gdata.horizontalAlignment = SWT.FILL;
		gdata.verticalAlignment = SWT.FILL;
		gdata.grabExcessHorizontalSpace = true;
		gdata.grabExcessVerticalSpace =true;
		gdata.minimumHeight = 100;
		gdata.minimumWidth = 100;
		
		downloading = new TableViewer(composite, SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
		DownloadingTableColumns.configureTable(downloading, getSite());
		downloading.setContentProvider(new TableContentProvider());
		downloading.setLabelProvider(new TableLabelProvider());
		downloading.setInput(Activator.getDefault().getRadioScheduler().getDownloader().getDownloadingItems());
		downloading.getTable().setLayoutData(gdata);
		
		downloading.addSelectionChangedListener(new ISelectionChangedListener() {
			
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				selectionProviderIntermediate.setSelectionProviderDelegate(event.getSelectionProvider());
				selectionProviderIntermediate.fireSelectionChanged(event.getSelection());
			}
		});

		ColumnViewerToolTipSupport.enableFor(downloading,ToolTip.NO_RECREATE);

		fontRegistry = new FontRegistry(getSite().getShell().getDisplay());
	    fontRegistry.put("processedFont", new FontData[]{new FontData("Arial", 8, SWT.ITALIC)} );
	    fontRegistry.put("notProcessedFont", new FontData[]{new FontData("Arial", 8, SWT.BOLD)} );
	    fontRegistry.put("preparingFont", new FontData[]{new FontData("Arial", 8, SWT.BOLD)} );

	
		justPoppedLabel.setFont(fontRegistry.get("preparingFont"));
		shutdownDate.setFont(fontRegistry.get("preparingFont"));
	}

	private Composite createInformationPane(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.numColumns = 4;
		composite.setLayout(layout);

		GridData  gdata = new GridData();
		CLabel preparingLabel = new CLabel(composite, SWT.NONE);
		preparingLabel.setLayoutData(gdata);
		preparingLabel.setText("Pripravuje se:");

		gdata = new GridData();
		gdata.horizontalSpan = 1;
		gdata.horizontalAlignment = SWT.FILL;
		gdata.grabExcessHorizontalSpace = true;

		justPoppedLabel = new CLabel(composite, SWT.NONE);
		justPoppedLabel.setLayoutData(gdata);


		gdata = new GridData();
		CLabel shutDownLabel = new CLabel(composite, SWT.NONE);
		shutDownLabel.setLayoutData(gdata);
		shutDownLabel.setText("Datum vypnuti:");
		
		
		gdata = new GridData();
		gdata.horizontalSpan = 1;
		gdata.horizontalAlignment = SWT.FILL;
		gdata.grabExcessHorizontalSpace = true;

		shutdownDate = new CLabel(composite, SWT.NONE);
		shutdownDate.setLayoutData(gdata);
		
		return composite;
	}
	
	@Override
	public void setFocus() {
		// TODO Auto-generated method stub
	}

	@Override
	public void init(IViewSite site) throws PartInitException {
		super.init(site);
	}

	@Override
	public void init(IViewSite site, IMemento memento) throws PartInitException {
		super.init(site, memento);
	}

	
	
	@Override
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
		LOGGER.info("part == "+part.getTitle());
		LOGGER.info("selection == "+selection);
	}



	class TableLabelProvider extends StyledCellLabelProvider   {

		
		
		@Override
		public String getToolTipText(Object element) {
			return element.toString();
		}

		public String getColumnText(Object element, int columnIndex) {
			if (element instanceof PlannedItem) {
				PlannedTableColumns column = PlannedTableColumns.values()[columnIndex];
				return column.getPlannedRecordingTextValue((PlannedItem) element);
			} else {
				DownloadingTableColumns column = DownloadingTableColumns.values()[columnIndex];
				return column.getDownloadingItemTextValue((DownloadingItem) element);
			}
		}

		@Override
		public void update(final ViewerCell cell) {
			cell.setText(getColumnText(cell.getElement(), cell.getColumnIndex()));
			grayProcessed(cell);
			super.update(cell);
		}

		private void grayProcessed(final ViewerCell cell) {
			if (cell.getElement().getClass().equals(DownloadingItem.class)) {
				DownloadingItem item = (DownloadingItem) cell.getElement();
				if (item.getProcessState().equals(ProcessStates.PROCESSED)) {
					StyleRange styleRange = new StyleRange(); {
						styleRange.start = 0;
						styleRange.length = getColumnText(cell.getElement(), cell.getColumnIndex()).length();
						styleRange.font = fontRegistry.get("processedFont");
					}
					Color gray = getSite().getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY);
					cell.setBackground(gray);
					cell.setStyleRanges(new StyleRange[] {styleRange});
				} else {
					StyleRange styleRange = new StyleRange(); {
						styleRange.start = 0;
						styleRange.length = getColumnText(cell.getElement(), cell.getColumnIndex()).length();
						//styleRange.font = fontRegistry.get("notProcessedFont");
					}
					cell.setStyleRanges(new StyleRange[] {styleRange});
				}
			}
		}		
		
		
		
	}
	
	static class TableContentProvider implements IStructuredContentProvider {
		
		public static final Logger LOGGER = Logger.getLogger(TableContentProvider.class.getName());
		
		
		@Override
		public void dispose() {
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {

		}

		@Override
		public Object[] getElements(Object inputElement) {
			return  (Object[]) inputElement;
		}
	}
	
	
	enum PlannedTableColumns {
		TITULEK("Titulek", 200, true) {

			@Override
			public String getPlannedRecordingTextValue(PlannedItem item) {
				return item.getTitle();
			}
		}, 
		STANICE("Stanice",100, true) {

			@Override
			public String getPlannedRecordingTextValue(PlannedItem item) {
				return item.getStation().name();
			}
			
		},
		NAPLANOVANO("Zacatek",100, true) {

			@Override
			public String getPlannedRecordingTextValue(PlannedItem item) {
				return TABLE_DATE_FORMATTER.format(item.getPlannedDate());
			}
		},
		STOP("Konec",100,true){

			@Override
			public String getPlannedRecordingTextValue(PlannedItem item) {
				StopDownloadCondition sc = item.getCondition();
				return TABLE_DATE_FORMATTER.format(((StopTimeCondition)sc).getStopDate());
			}
		};


		public abstract String getPlannedRecordingTextValue(PlannedItem item);
		
		private String text;
		private int width;
		private boolean resizable;

		private PlannedTableColumns(String text, int width, boolean resizable) {
			this.text = text;
			this.width = width;
			this.resizable = resizable;
		}

		public String getText() {
			return text;
		}

		public int getWidth() {
			return width;
		}

		public boolean isResizable() {
			return resizable;
		}
		
		static void configureTable(TableViewer tableViewer) {
			PlannedTableColumns[] values = values();
			for (PlannedTableColumns col : values) {
				TableViewerColumn swtCol = new TableViewerColumn(tableViewer, SWT.NONE);
				swtCol.getColumn().setText(col.getText());
				swtCol.getColumn().setWidth(col.getWidth());
				swtCol.getColumn().setMoveable(false);
				swtCol.getColumn().setResizable(col.isResizable());
			}

			Table table = tableViewer.getTable();
			table.setHeaderVisible(true);
			table.setLinesVisible(true);
		}
	}
	
	
	
	static class DownloadingItemColumnLabelProvider extends StyledCellLabelProvider {
		
		IWorkbenchSite workbenchSite;
		
		
		DownloadingItemColumnLabelProvider(IWorkbenchSite workbenchSite) {
			super();
			this.workbenchSite = workbenchSite;
		}


		@Override
		public void update(ViewerCell cell) {
			DownloadingItem item = (DownloadingItem) cell.getElement();
			if (item.getProcessState() == ProcessStates.PROCESSED) {
				Color gray = workbenchSite.getShell().getDisplay().getSystemColor(SWT.COLOR_GRAY);
				cell.setBackground(gray);
			} else {
				Color white = workbenchSite.getShell().getDisplay().getSystemColor(SWT.COLOR_WHITE);
				cell.setBackground(white);
			}
			
		}
		
	}

	
	enum DownloadingTableColumns {

		TITULEK("Titulek", 200, true) {
			@Override
			public String getDownloadingItemTextValue(DownloadingItem item) {
				return item.getTitle();
			}
			
		},
		
		STANICE("Stanice", 100, true) {

			@Override
			public String getDownloadingItemTextValue(DownloadingItem item) {
				return item.getPlaylistEntry().getStation().name();
			}

			
		},
		
		STATE("Stav",80,true){

			@Override
			public String getDownloadingItemTextValue(DownloadingItem item) {
				return item.getProcessState().name();
			}

		},

		START("Zacatek",100,true){

			@Override
			public String getDownloadingItemTextValue(DownloadingItem item) {
				return TABLE_DATE_FORMATTER.format(item.getDate());
			}

		},
		STOP("Konec",100,true){

			@Override
			public String getDownloadingItemTextValue(DownloadingItem item) {
				StopDownloadCondition sc = item.geStopDownloadingCondition();
				if (sc != null) return TABLE_DATE_FORMATTER.format(((StopTimeCondition)sc).getStopDate());
				else return "";
			}
		}
		
		;

		private DownloadingTableColumns(String text, int width, boolean resizable) {
			this.text = text;
			this.width = width;
			this.resizable = resizable;
		}

		public abstract String getDownloadingItemTextValue(DownloadingItem item);
		
		private String text;
		private int width;
		private boolean resizable;
		
		public String getText() {
			return text;
		}

		public int getWidth() {
			return width;
		}

		public boolean isResizable() {
			return resizable;
		}

		static void configureTable(TableViewer tableViewer, IWorkbenchSite workbenchSite) {
			DownloadingTableColumns[] values = values();
			for (DownloadingTableColumns col : values) {
				TableViewerColumn swtCol = new TableViewerColumn(tableViewer, SWT.NONE);
				swtCol.setLabelProvider(new DownloadingItemColumnLabelProvider(workbenchSite));
				swtCol.getColumn().setText(col.getText());
				swtCol.getColumn().setWidth(col.getWidth());
				swtCol.getColumn().setMoveable(false);
				swtCol.getColumn().setResizable(col.isResizable());
			}

			Table table = tableViewer.getTable();
			table.setHeaderVisible(true);
			table.setLinesVisible(true);
		}
	}

	@Override
	public void startDownloading() {
		new SyncExecTemplate(getSite(), new Runnable() {
			@Override
			public void run() {
				refresh();
			}
		}).execute();
	}

	@Override
	public void refreshInterval() {
		new SyncExecTemplate(getSite(), new Runnable() {
			@Override
			public void run() {
				refresh();
			}
		}).execute();
	}
	
	
	@Override
	public void exceptionOccured(final Throwable arg0) {
		// spatny descriptor radia
		if (arg0 instanceof IvalidPlaylistContentException) {
			new SyncExecTemplate(getSite(), new Runnable() {
				@Override
				public void run() {
					IvalidPlaylistContentException plex = (IvalidPlaylistContentException) arg0;
					MessageDialog.openError(getSite().getShell(), "Spatny playlist radia", "Obsah adresy:"+plex.getContent());
				}
			}).execute();
			
		// genericka vyjimka
		} else {
			new SyncExecTemplate(getSite(), new Runnable() {
				@Override
				public void run() {
					StringWriter stringWriter = new StringWriter();
					arg0.printStackTrace(new PrintWriter(stringWriter));
					MessageDialog.openError(getSite().getShell(), arg0.getClass().getName(), stringWriter.toString());
				}
			}).execute();
		}
	}

	public void refresh() {
		PlannedItem[] plannedItems = Activator.getDefault().getRadioScheduler().getPlanner().getPlannedItems();
		ContentView.this.planned.setInput(plannedItems);
		DownloadingItem[] downloadingItems = Activator.getDefault().getRadioScheduler().getDownloader().getDownloadingItems();
		ContentView.this.downloading.setInput(downloadingItems);
		
		PlannedItem itm = Activator.getDefault().getRadioScheduler().getPlanner().getJustPopped();
		if (itm !=null) {
			justPoppedLabel.setText(itm.getTitle()+" ("+itm.getStation()+")");
		} else {
			justPoppedLabel.setText("");
		}
		
		Date sdate = Activator.getDefault().getRadioScheduler().getShutdownSystemDate();
		if (sdate != null) {
			shutdownDate.setText(TABLE_DATE_FORMATTER.format(sdate));
		} else {
			shutdownDate.setText("");
		}
		
	}
	

	@Override
	public void stopDownloading(final DownloadingItem item) {
		new SyncExecTemplate(getSite(), new Runnable() {
			@Override
			public void run() {
				refresh();
			}
		}).execute();

//
//		final Shell shell = getSite().getShell();
//		shell.getDisplay().asyncExec(new Runnable() {
//			
//			@Override
//			public void run() {
//				ProcessBuilder processBuilder = new ProcessBuilder("oggdec",item.getFile().getAbsolutePath(),"-t",item.getFile().getAbsolutePath()+".wav");
//				try {
//					Process start = processBuilder.start();
//					ByteArrayOutputStream bos  =new  ByteArrayOutputStream();
//					InputStream inputStream = start.getInputStream();
//					//IOUtils.copyStreams(inputStream, bos);
//					int waitFor = start.waitFor();
//					MessageBox messageBox = new MessageBox(shell);
//					messageBox.setMessage("Vytvoreno");
//					
//				} catch (IOException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				} catch (InterruptedException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
//		});
	}


	@Override
	public void shutDown() {
		// TODO Auto-generated method stub
		
	}
}
